איך מחפשים במסד את מה שאי אפשר למצוא עם like
מה זה חיפוש טקסט מלא ולמה הוד עדיף - קרוא בהמשך
Full Text Search — חיפוש טקסט מלא היא טכניקת חיפוש טקסט במסד נתונים. בחיפוש טקסט מלא מנוע החיפוש עובר על כל מילה ומילה בטקסט ובודק האם היא מתאימה לשאילתת החיפוש.
1. full text search הרבה יותר מהיר מ-like
full text search .2 הרבה יותר מדויק מ-like
אינדוקס טקסט
טקסט בשדות טקסט מלא מאונדקס. mysql עוברת על הטקסט, בוחנת את המילים שקיימות בו ושומרת רשימה נפרדת — אילו מילים מכיל אותו טקסט. כאשר מתבצע חיפוש על שדה הטקסט הזה, mysql ניגשת לרשימת המילים שלה, בודקת במהירות האם המילה המחופשת קיימת שם או לא ומחזירה בזריזות את התשובה.
לאומתה במקרה של like היה חייב המסד לנתח את הטקסט מחדש (לשלוף אותו מהקובץ שבו הוא שמור, לפענח את המחרוזת ולבצע השוואת מחרוזות איטית.
דיוק חיפוש
הבסה של like
נניח שהטקסט שלכם הוא 'inhibited search'
חיפוש המילה hi לפי %hi% ימצא גם את המילה inhibited כיוון שגם בה יש hi.
כדי לפתור בעיה זו עם like נצטרך לחפש את hi עם רווח לפני ואחרי המילה כדי למצוא אך ורק מילים נפרדות. בנוסף לזה נצטרך לכתוב תנאי נוסף למקרה שהטקסט מתחיל במילה hi (כי לפניה לא יהיה רווח) וגם לכתוב תנאי נוסף למקרה שהטקסט נגמר ב hi שאחריו אין רווח.
למקרה שחשבתם שזה הכל — חבל. הרי הטקסט שלנו יכול להכיל את המילה hi ואחריה פסיק, נקודה, סימן פיסוק אחר, נקודה, מעבר שורה או כל דבר אחר. ניסיון למצוא את hi הופך לכמות בלתי מוגבלת של השוואת שהמסד יצטרך לבצע.
אלה עם כן אתם מרגישים שלמשתמשים שלכם התוצאה של inhibited search היא די רלוונטית בחיפוש אחר hi. כנראה שאין טעם להמשיך לקרוא אם זה ככה :)
הטקסט המלא
בנוסף לכל, חיפוש טקסט מלא מפענח את הטקסט ומאפשר חיפוש לקסי, שיאפשר למצוא מילים מאותו שורש ומבנה. בחיפוש של המילה 'אוכל' נוכל למצוא גם את אוכלת, אוכלים, אוכלות.
איך יוצרים את זה?!
יוצרים שדה רגיל לחלוטין מסוג Text
מסמנים אותו ולוחצים על כפטור ה-Full Text
זהו זה, כל התהליך. mysql תדאג לבנות אינדקס טקסט מלא עבור השדה הזה לבד.
חיפוש בשדה טקסט מלא
השאילתה המתאימה לחיפוש בשדה טקסט מלא היא match against
SELECT * FROM `table1` WHERE MATCH(`textcolumn`) AGAINST('אוכל')
זהו זה. החיפוש עובד הרבה יותר מהר ומדויק יותר מזכות חישוב רלוונטיות של הטקסט למילה. בפועל match against מחשבת עד כמה הטקסט רלוונטי למילה המסוימת ובוחר את כל השורות בהם הרלוונטיות גדולה מ 50%. את הרלוונטיות שעליה החליט מנוע החיפוש אפשר לראות בעזרת השליפה
SELECT *,MATCH(`textcolumn`) AGAINST('אוכל') FROM `table1`
טקסט מלא רק בטבלאות MyIsam
mysql תומכת באינדוקס טקסט מלא רק עבור טבלאות מסוג myisam. בגרסאות האחרונות של mysql סוג הטבלה כברירת המחדל הוא InnoDB שלא תומך באינדוקס טקסט מלא. במקרה והינכם חייבים להשתמש ב-InnoDB עבור אותה טבלה שעליה מבוצע החיפוש — השתמשו ב SphinxSearch.
נ.ב. על חיפוש שדה מלא יש הגבלה לאורך מחרוזת החיפוש. מחרוזת החיפוש חייבת להיות באורך ארבעה תווים לפחות. כלומר לא ניתן לחפש את המילה 'yes' באמצעות חיפוש טקסט מלא. ההגבלה הזו נועדה להקל על מנוע החיפוש מפני חיפוש מילים שכיחות מדי כמו the.
כהמשך אפשר גם לראות ולהבין את ההבדל בין סוגי הטבלאות, myIsam, innoDB והשאר.
תגובות לכתבה:
אבל נגיד אני רוצה לעשות אשכולות וחיפוש בכותרת של האשכול..
מה הטעם בישביל קוטרת שמקסימום התווים שלה זה 30 תווים ליצור שד טקסט?
מיילה הודעה עצמה אבל הכותרת של הנושא ממש מיותר יוצרים שדא מסוג varchar(30) .
יש עוד פיתרו בישביל זה?
על שדה מסוג varchar גם כן אפשר ליצור אינדקס טקסט מלא.
בLIKE אתה לא צריך לעשות 3 מקרים,מספיק לך %text% כדי למצוא את הטקסט בכל מקום... לדוגמה:http://pixup2.me/search.php?a=s&q=test
טוב נתקלתי בבעיה עם LIKE נגיד ואני רוצה לחפש epic fail ויש לי קובץ בשם epic-fail זה לא מוצא לי,אולי אתה יודע מה עלי לעשות?
>> בLIKE אתה לא צריך לעשות 3 מקרים
כן, תודה שהזכרת. צריך הרבה יותר. עדכנתי הכתבה
>> טוב נתקלתי בבעיה עם LIKE
אין לזה פתרון עם like.
חיפוש טקסט מלא הוא הפתרון היחידי שלך. לא סתם המציאו אותו
עזרה במקרים פרטיים אשמח להגיש בפורום :)
מצטער על הבורות, אבל אם בחיפוש אני אקליד שם של משתמש כלשהו באתר מסוים, זה לא יציג לי את שם המשתמש והסיסמא?
דרך אגב, העליתם לאתר הזה מדריכים לשימוש ב-SQL. אם כן אז תשלחו לי בבקשה את הקישורים אליהם.
תודה!
לא עובד לא העניין של משפחות המילים (אם מכניסים אוכל זה גם מוציא אוכלים, אוכלות וכו')...
למען האמת כל החיפוש full text עבד לי בכלל, אבל כשהוספתי IN BOOLEAN MODE זה עבד בערך.
צריך לתקן ולומר שזה תקף רק לאנגלית ולא תמיד.
המדריך עזר לי מאוד אבל נתקלתי בבעיה,
החיפוש עובד אצלי בצורה של case-sensitive. קראתי שזה לא אמור להיות ככה, אלא אם מגדירים את השדה כ-latin1_bin או משהו כזה, אבל אצלי הוא latin1_swedish_ci.
איך מטפלים בבעיה הזאת
בברירת המחדל בחיפוש הוא case-INsensitive, אלה אם כן באמת מגדירים את השדה בתור bin_.
אתה בטוח שהשדות והטבלה עצמה הם ci ?
תוכל לנסות את השליפה הבאה:
SELECT * FROM mytable WHERE MATCH(text_field) AGAINST('BANKING' IN BOOLEAN MODE) COLLATE latin1_general_ci;
תודה
הוספתי מה שאמרת וזה עובד מצויין :)
איך משתמשים בספינקס?
זה תכנה נפרדת שצריך להתקין על השרת ולקנפג.
את כל ההסברים אפשר למצוא באתר שלהם.
http://sphinxsearch.com/docs/